package factory.one.service;

import factory.one.config.Conf;
import factory.one.entity.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 支绍昆
 * 2024/2/19
 * 导出服务
 **/
@Service
public class ExportService {

    private final BatchService batchService;
    private final Conf conf;
    private final CustomService customService;
    private final DeliverService deliverService;
    private final DeliverItemService deliverItemService;
    private final MoneyService moneyService;
    private final OrderService orderService;
    private final ProductService productService;
    private final BigDecimal BD100 = new BigDecimal(100);

    public ExportService(BatchService batchService,
                         Conf conf,
                         CustomService customService,
                         DeliverService deliverService,
                         DeliverItemService deliverItemService,
                         MoneyService moneyService,
                         OrderService orderService,
                         ProductService productService) {
        this.batchService = batchService;
        this.conf = conf;
        this.customService = customService;
        this.deliverService = deliverService;
        this.deliverItemService = deliverItemService;
        this.moneyService = moneyService;
        this.orderService = orderService;
        this.productService = productService;
    }

    public Workbook exportOrder(Long orderId) {
        int rowIndex = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

        Order order = orderService.getById(orderId);

        Workbook workbook = new SXSSFWorkbook();
        CellStyle borderStyle = createBorderStyle(workbook);
        CellStyle titleStyle = createBorderStyle(workbook);
        titleStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        Sheet sheet = workbook.createSheet("订单");

        //订单信息
        Row r0 = sheet.createRow(0);
        cellCreateAndSet(r0, 0, titleStyle, "订单编号:");
        cellCreateAndSet(r0, 1, borderStyle, order.getCode());
        cellCreateAndSet(r0, 2, titleStyle, "数据标识:");
        cellCreateAndSet(r0, 3, borderStyle, order.getId());
        cellCreateAndSet(r0, 4, titleStyle, "创建用户:");
        cellCreateAndSet(r0, 5, borderStyle, order.getCreateUser());
        Row r1 = sheet.createRow(1);
        cellCreateAndSet(r1, 0, titleStyle, "客户:");
        cellCreateAndSet(r1, 1, borderStyle, customService.getById(order.getCustomId()).getName());
        cellCreateAndSet(r1, 2, borderStyle, "");
        cellCreateAndSet(r1, 3, borderStyle, "");
        cellCreateAndSet(r1, 4, titleStyle, "创建时间:");
        cellCreateAndSet(r1, 5, borderStyle, sdf.format(order.getCreateTime()));

        //产品信息
        Map<Integer, Long> indexMapBatchId = new HashMap<>();
        List<Batch> batchList = batchService.list(orderId);
        Row r3 = sheet.createRow(3);
        Row r4 = sheet.createRow(4);
        Row r5 = sheet.createRow(5);
        Row r6 = sheet.createRow(6);
        Row r7 = sheet.createRow(7);
        Row r8 = sheet.createRow(8);
        cellCreateAndSet(r3, 0, titleStyle, "产品:");
        cellCreateAndSet(r4, 0, titleStyle, "订货数量:");
        cellCreateAndSet(r5, 0, titleStyle, "生产数量:");
        cellCreateAndSet(r6, 0, titleStyle, "发货数量:");
        cellCreateAndSet(r7, 0, titleStyle, "退货数量:");
        cellCreateAndSet(r8, 0, titleStyle, "单价:");
        for (int i = 0; i < batchList.size(); i++) {
            int index = i + 1;
            Batch batch = batchList.get(i);
            indexMapBatchId.put(index, batch.getId());
            cellCreateAndSet(r3, index, borderStyle, productService.getById(batch.getProductId()).getName());
            cellCreateAndSet(r4, index, borderStyle, batch.getOrderNum());
            cellCreateAndSet(r5, index, borderStyle, batch.getProduceNum());
            cellCreateAndSet(r6, index, borderStyle, batch.getSendNum());
            cellCreateAndSet(r7, index, borderStyle, batch.getRefundNum());
            cellCreateAndSet(r8, index, borderStyle, toYuan(batch.getPrice().longValue()));
        }

        //发货记录
        sheet.createRow(9).createCell(0).setCellValue("发货详情:");
        List<Deliver> deliverList = deliverService.listHistory(orderId);
        rowIndex = 10;
        for (Deliver deliver : deliverList) {
            Row row = sheet.createRow(rowIndex++);
            cellCreateAndSet(row, 0, borderStyle, deliver.getSequence() + "次");
            List<DeliverItem> itemList = deliverItemService.listByDeliver(deliver.getId());
            for (int i = 0; i < batchList.size(); i++) {
                int index = i + 1;
                DeliverItem item = findItem(itemList, indexMapBatchId.get(index));
                cellCreateAndSet(row, index, borderStyle, Objects.isNull(item) ? 0 : item.getNumber());
            }
            cellCreateAndSet(row, batchList.size() + 1, borderStyle, sdf.format(deliver.getCreateTime()));
            cellCreateAndSet(row, batchList.size() + 2, borderStyle, deliver.getCreateUser());
        }

        //回款详情
        rowIndex++;
        sheet.createRow(rowIndex++).createCell(0).setCellValue("回款详情:");
        List<Money> moneyList = moneyService.listByOrder(orderId);
        for (Money money : moneyList) {
            Row row = sheet.createRow(rowIndex++);
            cellCreateAndSet(row, 0, borderStyle, sdf.format(money.getOccurTime()));
            cellCreateAndSet(row, 1, borderStyle, toYuan(money.getAmount()));
            cellCreateAndSet(row, 2, borderStyle, money.getContent());
            cellCreateAndSet(row, 3, borderStyle, money.getCreateUser());
            cellCreateAndSet(row, 4, borderStyle, sdf.format(money.getCreateTime()));
        }

        return workbook;
    }

    public Workbook exportDelivery(Long orderId) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Workbook workbook = new SXSSFWorkbook();
        CellStyle borderStyle = createBorderStyle(workbook);
        CellStyle titleStyle = createBorderStyle(workbook);
        titleStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Sheet sheet = workbook.createSheet("发货详单");

        Order order = orderService.getById(orderId);
        sheet.createRow(1).createCell(1).setCellValue(conf.getCompany());
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 3));
        Row r2 = sheet.createRow(2);
        r2.createCell(1).setCellValue("订单编号:");
        r2.createCell(2).setCellValue(order.getCode());

        //产品信息
        Map<Integer, Long> indexMapBatchId = new HashMap<>();
        List<Batch> batchList = batchService.list(orderId);
        Row r3 = sheet.createRow(3);
        Row r4 = sheet.createRow(4);
        Row r5 = sheet.createRow(5);
        cellCreateAndSet(r3, 1, titleStyle, "产品名称");
        cellCreateAndSet(r4, 1, titleStyle, "订货数量");
        cellCreateAndSet(r5, 1, titleStyle, "累计发货");
        for (int i = 0; i < batchList.size(); i++) {
            int index = i + 2;
            Batch batch = batchList.get(i);
            indexMapBatchId.put(index, batch.getId());
            cellCreateAndSet(r3, index, titleStyle, productService.getById(batch.getProductId()).getName());
            cellCreateAndSet(r4, index, borderStyle, batch.getOrderNum());
            cellCreateAndSet(r5, index, borderStyle, batch.getSendNum());
        }

        //发货记录
        List<Deliver> deliverList = deliverService.listHistory(orderId);
        int rowIndex = 6;
        for (Deliver deliver : deliverList) {
            Row row = sheet.createRow(rowIndex++);
            cellCreateAndSet(row, 1, titleStyle, deliver.getSequence() + "次");
            List<DeliverItem> itemList = deliverItemService.listByDeliver(deliver.getId());
            for (int i = 0; i < batchList.size(); i++) {
                int index = i + 2;
                DeliverItem item = findItem(itemList, indexMapBatchId.get(index));
                cellCreateAndSet(row, index, borderStyle, Objects.isNull(item) ? 0 : item.getNumber());
            }
            cellCreateAndSet(row, batchList.size() + 2, null, sdf.format(deliver.getCreateTime()));
            cellCreateAndSet(row, batchList.size() + 3, null, deliver.getCreateUser());
        }

        sheet.setColumnWidth(batchList.size() + 2, 11 * 256);

        return workbook;
    }


    private DeliverItem findItem(List<DeliverItem> list, Long batchId) {
        for (DeliverItem item : list) {
            if (item.getBatchId().equals(batchId)) {
                return item;
            }
        }
        return null;
    }

    //金额分转元
    private String toYuan(Long fen) {
        BigDecimal value = new BigDecimal(fen);
        return value.divide(BD100, 2, RoundingMode.HALF_UP).toString();
    }

    private CellStyle createBorderStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        return cellStyle;
    }

    private Cell cellCreateAndSet(Row row, int index, CellStyle style, String value) {
        Cell cell = row.createCell(index);
        cell.setCellStyle(style);
        cell.setCellValue(value);
        return cell;
    }

    private Cell cellCreateAndSet(Row row, int index, CellStyle style, Long value) {
        Cell cell = row.createCell(index);
        cell.setCellStyle(style);
        cell.setCellValue(value);
        return cell;
    }

    private Cell cellCreateAndSet(Row row, int index, CellStyle style, Integer value) {
        Cell cell = row.createCell(index);
        cell.setCellStyle(style);
        cell.setCellValue(value);
        return cell;
    }

}
